home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / hplip / fax / soapfax.py < prev   
Text File  |  2008-10-13  |  30KB  |  719 lines

  1. # -*- coding: utf-8 -*-
  2. #
  3. # (c) Copyright 2003-2007 Hewlett-Packard Development Company, L.P.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  18. #
  19. # Author: Don Welch
  20. #
  21.  
  22. from __future__ import division
  23.  
  24. # Std Lib
  25. import sys
  26. import os
  27. import time
  28. import cStringIO
  29. import urllib # TODO: Replace with urllib2 (urllib is deprecated in Python 3.0)
  30. import re
  31.  
  32. # Local
  33. from base.g import *
  34. from base.codes import *
  35. from base import device, utils, codes, dime
  36. from fax import *
  37.  
  38. #import xml.parsers.expat as expat
  39.  
  40.  
  41. # **************************************************************************** #
  42.  
  43. http_result_pat = re.compile("""HTTP/\d.\d\s(\d+)""", re.I)
  44.  
  45.  
  46. TIME_FORMAT_AM_PM = 1
  47. TIME_FORMAT_24HR = 2
  48.  
  49. DATE_FORMAT_MM_DD_YYYY = 1
  50. DATE_FORMAT_DD_MM_YYYY = 2
  51. DATE_FORMAT_YYYY_MM_DD = 3
  52.  
  53. AM = 1
  54. PM = 0
  55.  
  56. HTTP_OK = 200
  57. HTTP_ERROR = 500
  58.  
  59. PIXELS_PER_LINE = 2528
  60.  
  61.  
  62. # **************************************************************************** #
  63. class SOAPFaxDevice(FaxDevice):
  64.  
  65.     def __init__(self, device_uri=None, printer_name=None,
  66.                  callback=None, 
  67.                  fax_type=FAX_TYPE_NONE,
  68.                  disable_dbus=False):
  69.  
  70.         FaxDevice.__init__(self, device_uri, 
  71.                            printer_name, 
  72.                            callback, fax_type,
  73.                            disable_dbus)
  74.  
  75.         self.send_fax_thread = None
  76.         self.upload_log_thread = None
  77.  
  78.         if self.bus == 'net':
  79.             self.http_host = self.host
  80.         else:
  81.             self.http_host = 'localhost'
  82.  
  83.  
  84.     def post(self, url, post):
  85.         s = []
  86.         for k, v in post.items():
  87.             s.append("%s=%s" % (k, urllib.quote(str(v))))
  88.  
  89.         s = '&'.join(s)
  90.  
  91.         log.debug(s)
  92.  
  93.         data = """POST %s HTTP/1.1
  94. Connection: Keep-alive
  95. User-agent: hplip/2.0
  96. Host: %s
  97. Content-length: %d
  98. Cache-control: No-cache
  99.  
  100. %s""" % (url, self.http_host, len(s), s)
  101.  
  102.         log.log_data(data)
  103.         self.writeEWS(data)
  104.         ret = cStringIO.StringIO()
  105.         
  106.         while self.readEWS(4096, ret, timeout=5):
  107.             pass
  108.             
  109.         ret = ret.getvalue()
  110.         
  111.         log.log_data(ret)
  112.  
  113.         self.closeEWS()
  114.  
  115.         match = http_result_pat.match(ret)
  116.  
  117.         try:
  118.             code = int(match.group(1))
  119.         except (ValueError, TypeError):
  120.             code = HTTP_ERROR
  121.  
  122.         return code == HTTP_OK
  123.         
  124.  
  125.     def setPhoneNum(self, num):
  126.         return self.post("/hp/device/set_config.html", {"FaxNumber": str(num)})
  127.  
  128.         
  129.     def getPhoneNum(self):
  130.         stream = cStringIO.StringIO()
  131.         self.getEWSUrl("/hp/device/settings_fax_setup_wizard.xml", stream)
  132.         fax_setup = utils.XMLToDictParser().parseXML(stream.getvalue())
  133.         return fax_setup['faxsetupwizard-faxvoicenumber-faxnumber']
  134.  
  135.     phone_num = property(getPhoneNum, setPhoneNum)
  136.  
  137.  
  138.     def setStationName(self, name): 
  139.         return self.post("/hp/device/set_config.html", {"FaxCompanyName": str(name)})
  140.  
  141.         
  142.     def getStationName(self):
  143.         stream = cStringIO.StringIO()
  144.         self.getEWSUrl("/hp/device/settings_fax_setup_wizard.xml", stream)
  145.         fax_setup = utils.XMLToDictParser().parseXML(stream.getvalue())
  146.         return fax_setup['faxsetupwizard-userinformation-faxcompanyname']
  147.  
  148.     station_name = property(getStationName, setStationName)
  149.  
  150.     
  151.     def setDateAndTime(self):
  152.         stream = cStringIO.StringIO()
  153.         self.getEWSUrl("/hp/device/settings_fax_setup_wizard.xml", stream)
  154.         fax_setup = utils.XMLToDictParser().parseXML(stream.getvalue())
  155.         timeformat = fax_setup['faxsetupwizard-time-timeformat']
  156.  
  157.         try:
  158.             timeformat = int(timeformat)
  159.         except (ValueError, TypeError):
  160.             timeformat = TIME_FORMAT_AM_PM
  161.  
  162.         log.debug("timeformat: %d" % timeformat)
  163.  
  164.         dateformat = fax_setup['faxsetupwizard-date-dateformat']
  165.  
  166.         try:
  167.             dateformat = int(dateformat)
  168.         except (ValueError, TypeError):
  169.             dateformat = DATE_FORMAT_DD_MM_YYYY
  170.  
  171.         log.debug("dateformat: %d" % dateformat)
  172.  
  173.         t = time.localtime()
  174.         hr = t[3]
  175.  
  176.         am_pm = PM
  177.         if t[3] < 12:
  178.             am_pm = AM
  179.  
  180.         if timeformat == TIME_FORMAT_AM_PM and hr > 12:
  181.             hr -= 12
  182.  
  183.         post = {"DateFormat" : dateformat,
  184.                 "Year" : t[0],
  185.                 "Month" : t[1],
  186.                 "Day" : t[2],
  187.                 "TimeFormat" : timeformat,
  188.                 "Hour" : hr,
  189.                 "Minute" : t[4]}
  190.  
  191.         if timeformat == TIME_FORMAT_AM_PM:
  192.             post['AM'] = am_pm
  193.  
  194.         return self.post("/hp/device/set_config.html", post)
  195.  
  196.  
  197.     def sendFaxes(self, phone_num_list, fax_file_list, cover_message='', cover_re='', 
  198.                   cover_func=None, preserve_formatting=False, printer_name='', 
  199.                   update_queue=None, event_queue=None):
  200.  
  201.         if not self.isSendFaxActive():
  202.  
  203.             self.send_fax_thread = SOAPFaxSendThread(self, self.service, phone_num_list, fax_file_list, 
  204.                                                      cover_message, cover_re, cover_func, 
  205.                                                      preserve_formatting, 
  206.                                                      printer_name, update_queue, 
  207.                                                      event_queue)
  208.  
  209.             self.send_fax_thread.start()
  210.             return True
  211.         else:
  212.             return False
  213.  
  214.  
  215. # **************************************************************************** #
  216. class SOAPFaxSendThread(FaxSendThread):
  217.     def __init__(self, dev, service, phone_num_list, fax_file_list, 
  218.                  cover_message='', cover_re='', cover_func=None, preserve_formatting=False,
  219.                  printer_name='', update_queue=None, event_queue=None):
  220.  
  221.         FaxSendThread.__init__(self, dev, service, phone_num_list, fax_file_list, 
  222.              cover_message, cover_re, cover_func, preserve_formatting,
  223.              printer_name, update_queue, event_queue)
  224.              
  225.         self.job_id = utils.gen_random_uuid()
  226.         log.debug("JobId: %s" % self.job_id)
  227.         
  228.         if dev.bus == 'net':
  229.             self.http_host = "%s:8295" % self.dev.host
  230.         else:
  231.             self.http_host = 'localhost:8295'
  232.         
  233.         #self.http_host = 'localhost'
  234.  
  235.  
  236.     def run(self):
  237.         #results = {} # {'file' : error_code,...}
  238.  
  239.         STATE_DONE = 0
  240.         STATE_ABORTED = 10
  241.         STATE_SUCCESS = 20
  242.         STATE_BUSY = 25
  243.         STATE_READ_SENDER_INFO = 30
  244.         STATE_PRERENDER = 40
  245.         STATE_COUNT_PAGES = 50
  246.         STATE_NEXT_RECIPIENT = 60
  247.         STATE_COVER_PAGE = 70
  248.         STATE_SINGLE_FILE = 80
  249.         STATE_MERGE_FILES = 90
  250.         STATE_SINGLE_FILE = 100
  251.         STATE_SEND_FAX = 110
  252.         STATE_CLEANUP = 120
  253.         STATE_ERROR = 130
  254.  
  255.         next_recipient = self.next_recipient_gen()
  256.  
  257.         state = STATE_READ_SENDER_INFO
  258.         self.rendered_file_list = []
  259.  
  260.         while state != STATE_DONE: # --------------------------------- Fax state machine
  261.             if self.check_for_cancel():
  262.                 state = STATE_ABORTED
  263.  
  264.             log.debug("STATE=(%d, 0, 0)" % state)
  265.  
  266.             if state == STATE_ABORTED: # --------------------------------- Aborted (10, 0, 0)
  267.                 log.error("Aborted by user.")
  268.                 self.write_queue((STATUS_IDLE, 0, ''))
  269.                 state = STATE_CLEANUP
  270.  
  271.  
  272.             elif state == STATE_SUCCESS: # --------------------------------- Success (20, 0, 0)
  273.                 log.debug("Success.")
  274.                 self.write_queue((STATUS_COMPLETED, 0, ''))
  275.                 state = STATE_CLEANUP
  276.  
  277.  
  278.             elif state == STATE_ERROR: # --------------------------------- Error (130, 0, 0)
  279.                 log.error("Error, aborting.")
  280.                 self.write_queue((STATUS_ERROR, 0, ''))
  281.                 state = STATE_CLEANUP
  282.  
  283.  
  284.             elif state == STATE_BUSY: # --------------------------------- Busy (25, 0, 0)
  285.                 log.error("Device busy, aborting.")
  286.                 self.write_queue((STATUS_BUSY, 0, ''))
  287.                 state = STATE_CLEANUP
  288.  
  289.  
  290.             elif state == STATE_READ_SENDER_INFO: # --------------------------------- Get sender info (30, 0, 0)
  291.                 log.debug("%s State: Get sender info" % ("*"*20))
  292.                 state = STATE_PRERENDER
  293.                 try:
  294.                     try:
  295.                         self.dev.open()
  296.                     except Error, e:
  297.                         log.error("Unable to open device (%s)." % e.msg)
  298.                         state = STATE_ERROR
  299.                     else:
  300.                         try:
  301.                             self.sender_name = self.dev.station_name
  302.                             log.debug("Sender name=%s" % self.sender_name)
  303.                             self.sender_fax = self.dev.phone_num
  304.                             log.debug("Sender fax=%s" % self.sender_fax)
  305.                         except Error:
  306.                             log.error("HTTP GET failed!")
  307.                             state = STATE_ERROR
  308.  
  309.                 finally:
  310.                     self.dev.close()
  311.  
  312.  
  313.             elif state == STATE_PRERENDER: # --------------------------------- Pre-render non-G4 files (40, 0, 0)
  314.                 log.debug("%s State: Pre-render non-G4 files" % ("*"*20))
  315.                 state = self.pre_render(STATE_COUNT_PAGES)
  316.  
  317.             elif state == STATE_COUNT_PAGES: # --------------------------------- Get total page count (50, 0, 0)
  318.                 log.debug("%s State: Get total page count" % ("*"*20))
  319.                 state = self.count_pages(STATE_NEXT_RECIPIENT)
  320.  
  321.             elif state == STATE_NEXT_RECIPIENT: # --------------------------------- Loop for multiple recipients (60, 0, 0)
  322.                 log.debug("%s State: Next recipient" % ("*"*20))
  323.                 state = STATE_COVER_PAGE
  324.  
  325.                 try:
  326.                     recipient = next_recipient.next()
  327.                     log.debug("Processing for recipient %s" % recipient['name'])
  328.                 except StopIteration:
  329.                     state = STATE_SUCCESS
  330.                     log.debug("Last recipient.")
  331.                     continue
  332.  
  333.                 recipient_file_list = self.rendered_file_list[:]
  334.  
  335.  
  336.             elif state == STATE_COVER_PAGE: # --------------------------------- Create cover page (70, 0, 0)
  337.                 log.debug("%s State: Render cover page" % ("*"*20))
  338.                 state = self.cover_page(recipient)
  339.  
  340.  
  341.             elif state == STATE_SINGLE_FILE: # --------------------------------- Special case for single file (no merge) (80, 0, 0)
  342.                 log.debug("%s State: Handle single file" % ("*"*20))
  343.                 state = self.single_file(STATE_SEND_FAX)
  344.  
  345.             elif state == STATE_MERGE_FILES: # --------------------------------- Merge multiple G4 files (90, 0, 0)
  346.                 log.debug("%s State: Merge multiple files" % ("*"*20))
  347.                 state = self.merge_files(STATE_SEND_FAX)
  348.  
  349.             elif state == STATE_SEND_FAX: # --------------------------------- Send fax state machine (110, 0, 0)
  350.                 log.debug("%s State: Send fax" % ("*"*20))
  351.                 state = STATE_NEXT_RECIPIENT
  352.  
  353.                 FAX_SEND_STATE_DONE = 0
  354.                 FAX_SEND_STATE_ABORT = 10
  355.                 FAX_SEND_STATE_ERROR = 20
  356.                 FAX_SEND_STATE_BUSY = 25
  357.                 FAX_SEND_STATE_SUCCESS = 30
  358.                 FAX_SEND_STATE_DEVICE_OPEN = 40
  359.                 FAX_SEND_STATE_BEGINJOB = 50
  360.                 FAX_SEND_STATE_DOWNLOADPAGES = 60
  361.                 FAX_SEND_STATE_ENDJOB = 70
  362.                 FAX_SEND_STATE_CANCELJOB = 80
  363.                 FAX_SEND_STATE_CLOSE_SESSION = 170
  364.  
  365.                 monitor_state = False
  366.                 fax_send_state = FAX_SEND_STATE_DEVICE_OPEN
  367.  
  368.                 while fax_send_state != FAX_SEND_STATE_DONE:
  369.  
  370.                     if self.check_for_cancel():
  371.                         log.error("Fax send aborted.")
  372.                         fax_send_state = FAX_SEND_STATE_ABORT
  373.  
  374.                     if monitor_state:
  375.                         fax_state = self.getFaxDownloadState() 
  376.                         if not fax_state in (pml.UPDN_STATE_XFERACTIVE, pml.UPDN_STATE_XFERDONE):
  377.                             log.error("D/L error state=%d" % fax_state)
  378.                             fax_send_state = FAX_SEND_STATE_ERROR
  379.                             state = STATE_ERROR
  380.  
  381.                     log.debug("STATE=(%d, %d, 0)" % (STATE_SEND_FAX, fax_send_state))
  382.  
  383.                     if fax_send_state == FAX_SEND_STATE_ABORT: # -------------- Abort (110, 10, 0)
  384.                         monitor_state = False
  385.                         fax_send_state = FAX_SEND_STATE_CANCELJOB
  386.                         state = STATE_ABORTED
  387.  
  388.                     elif fax_send_state == FAX_SEND_STATE_ERROR: # -------------- Error (110, 20, 0)
  389.                         log.error("Fax send error.")
  390.                         monitor_state = False
  391.                         fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
  392.                         state = STATE_ERROR
  393.  
  394.                     elif fax_send_state == FAX_SEND_STATE_BUSY: # -------------- Busy (110, 25, 0)
  395.                         log.error("Fax device busy.")
  396.                         monitor_state = False
  397.                         fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
  398.                         state = STATE_BUSY
  399.  
  400.                     elif fax_send_state == FAX_SEND_STATE_SUCCESS: # -------------- Success (110, 30, 0)
  401.                         log.debug("Fax send success.")
  402.                         monitor_state = False
  403.                         fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
  404.                         state = STATE_NEXT_RECIPIENT
  405.  
  406.                     elif fax_send_state == FAX_SEND_STATE_DEVICE_OPEN: # -------------- Device open (110, 40, 0)
  407.                         log.debug("%s State: Open device" % ("*"*20))
  408.                         fax_send_state = FAX_SEND_STATE_BEGINJOB
  409.                         try:
  410.                             self.dev.open()
  411.                         except Error, e:
  412.                             log.error("Unable to open device (%s)." % e.msg)
  413.                             fax_send_state = FAX_SEND_STATE_ERROR
  414.                         else:
  415.                             if self.dev.device_state == DEVICE_STATE_NOT_FOUND:
  416.                                 fax_send_state = FAX_SEND_STATE_ERROR
  417.                                 
  418.                     elif fax_send_state == FAX_SEND_STATE_BEGINJOB: # -------------- BeginJob (110, 50, 0)
  419.                         log.debug("%s State: BeginJob" % ("*"*20))
  420.                         
  421.                         try:
  422.                             ff = file(self.f, 'r')
  423.                         except IOError:
  424.                             log.error("Unable to read fax file.")
  425.                             fax_send_state = FAX_SEND_STATE_ERROR
  426.                             continue
  427.  
  428.                         try:
  429.                             header = ff.read(FILE_HEADER_SIZE)
  430.                         except IOError:
  431.                             log.error("Unable to read fax file.")
  432.                             fax_send_state = FAX_SEND_STATE_ERROR
  433.                             continue
  434.  
  435.                         magic, version, total_pages, hort_dpi, vert_dpi, page_size, \
  436.                             resolution, encoding, reserved1, reserved2 = self.decode_fax_header(header)
  437.  
  438.                         if magic != 'hplip_g3':
  439.                             log.error("Invalid file header. Bad magic.")
  440.                             fax_send_state = FAX_SEND_STATE_ERROR
  441.                         else:
  442.                             log.debug("Magic=%s Ver=%d Pages=%d hDPI=%d vDPI=%d Size=%d Res=%d Enc=%d" %
  443.                                       (magic, version, total_pages, hort_dpi, vert_dpi, page_size, 
  444.                                        resolution, encoding)) 
  445.                                        
  446.                         job_id = self.job_id
  447.                         delay = 0
  448.                         faxnum = recipient['fax'].encode('ascii')
  449.                         speeddial = 0
  450.                         
  451.                         if resolution == RESOLUTION_STD:
  452.                             res = "STANDARD"
  453.                         elif resolution == RESOLUTION_FINE:
  454.                             res = "FINE"
  455.                         elif resolution == RESOLUTION_300DPI:
  456.                             res = "SUPERFINE"
  457.                             
  458.                         soap = utils.cat(
  459. """<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><Fax:BeginJob xmlns:Fax="urn:Fax"><ticket xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Fax:Ticket"><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:string">$job_id</jobId><resolution xsi:type="Fax:Resolution">$res</resolution><delay xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:positiveInteger">$delay</delay><phoneNumber xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:string">$faxnum</phoneNumber><speedDial xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:positiveInteger">$speeddial</speedDial></ticket></Fax:BeginJob></SOAP-ENV:Body></SOAP-ENV:Envelope>""")
  460.  
  461.                         data = self.format_http(soap)
  462.                         log.log_data(data)
  463.                         
  464.                         if log.is_debug():
  465.                             file('beginjob.log', 'w').write(data)
  466.                             
  467.                         self.dev.openSoapFax()
  468.                         self.dev.writeSoapFax(data)
  469.                         ret = cStringIO.StringIO()
  470.                         
  471.                         while self.dev.readSoapFax(8192, ret, timeout=5):
  472.                             pass
  473.                             
  474.                         ret = ret.getvalue()
  475.                         
  476.                         if log.is_debug():
  477.                             file('beginjob_ret.log', 'w').write(ret)
  478.                             
  479.                         log.log_data(ret)
  480.                         self.dev.closeSoapFax()
  481.                         
  482.                         if self.get_error_code(ret) == HTTP_OK:
  483.                             fax_send_state = FAX_SEND_STATE_DOWNLOADPAGES
  484.                         else:
  485.                             fax_send_state = FAX_SEND_STATE_ERROR
  486.                         
  487.                         
  488.                     elif fax_send_state == FAX_SEND_STATE_DOWNLOADPAGES: # -------------- DownloadPages (110, 60, 0)
  489.                         log.debug("%s State: DownloadPages" % ("*"*20))
  490.                         page = StringIO()
  491.                         for p in range(total_pages):
  492.  
  493.                             if self.check_for_cancel():
  494.                                 fax_send_state = FAX_SEND_STATE_ABORT
  495.  
  496.                             if fax_send_state == FAX_SEND_STATE_ABORT:
  497.                                 break
  498.  
  499.                             try:
  500.                                 header = ff.read(PAGE_HEADER_SIZE)
  501.                             except IOError:
  502.                                 log.error("Unable to read fax file.")
  503.                                 fax_send_state = FAX_SEND_STATE_ERROR
  504.                                 continue
  505.  
  506.                             page_num, ppr, rpp, bytes_to_read, thumbnail_bytes, reserved2 = \
  507.                                 self.decode_page_header(header)
  508.  
  509.                             log.debug("Page=%d PPR=%d RPP=%d BPP=%d Thumb=%d" %
  510.                                       (page_num, ppr, rpp, bytes_to_read, thumbnail_bytes))
  511.  
  512.                             if ppr != PIXELS_PER_LINE:
  513.                                 log.error("Pixels per line (width) must be %d!" % PIXELS_PER_LINE)
  514.                             
  515.                             page.write(ff.read(bytes_to_read))
  516.                             thumbnail = ff.read(thumbnail_bytes) # thrown away for now (should be 0 read)
  517.                             page.seek(0)
  518.  
  519.                             try:
  520.                                 data = page.read(bytes_to_read)
  521.                             except IOError:
  522.                                 log.error("Unable to read fax file.")
  523.                                 fax_send_state = FAX_SEND_STATE_ERROR
  524.                                 break
  525.  
  526.                             if data == '':
  527.                                 log.error("No data!")
  528.                                 fax_send_state = FAX_SEND_STATE_ERROR
  529.                                 break
  530.                                 
  531.                             height = rpp 
  532.                             job_id = self.job_id
  533.                                 
  534.                             soap = utils.cat(
  535. """<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string" SOAP-ENV:mustUnderstand="1">$job_id</jobId></SOAP-ENV:Header><SOAP-ENV:Body><Fax:DownloadPage xmlns:Fax="urn:Fax"><height xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:positiveInteger">$height</height></Fax:DownloadPage></SOAP-ENV:Body></SOAP-ENV:Envelope>""")
  536.                                 
  537.                             m = dime.Message()
  538.                             m.add_record(dime.Record("cid:id0", "http://schemas.xmlsoap.org/soap/envelope/", 
  539.                                 dime.TYPE_T_URI, soap))
  540.                                 
  541.                             m.add_record(dime.Record("", "image/g4fax", dime.TYPE_T_MIME, data))
  542.                             
  543.                             output = cStringIO.StringIO()
  544.                             m.generate(output)
  545.                             data = self.format_http(output.getvalue(), content_type="application/dime")
  546.                             log.log_data(data)
  547.                             if log.is_debug():
  548.                                 file('downloadpages%d.log' % p, 'w').write(data)
  549.                             
  550.                             try:
  551.                                 self.dev.writeSoapFax(data)
  552.                             except Error:
  553.                                 fax_send_state = FAX_SEND_STATE_ERROR
  554.                             
  555.                             ret = cStringIO.StringIO()
  556.                             
  557.                             try:
  558.                                 while self.dev.readSoapFax(8192, ret, timeout=5):
  559.                                     pass
  560.                             except Error:
  561.                                 fax_send_state = FAX_SEND_STATE_ERROR
  562.                                 
  563.                             ret = ret.getvalue()
  564.                             
  565.                             if log.is_debug():
  566.                                 file('downloadpages%d_ret.log' % p, 'w').write(ret)
  567.                             
  568.                             log.log_data(ret)
  569.                             self.dev.closeSoapFax()
  570.                             
  571.                             if self.get_error_code(ret) != HTTP_OK:
  572.                                 fax_send_state = FAX_SEND_STATE_ERROR
  573.                                 break
  574.                             
  575.                             page.truncate(0)
  576.                             page.seek(0)
  577.                         
  578.                         else:
  579.                             fax_send_state = FAX_SEND_STATE_ENDJOB
  580.                             
  581.                         
  582.                     elif fax_send_state == FAX_SEND_STATE_ENDJOB: # -------------- EndJob (110, 70, 0)
  583.                         log.debug("%s State: EndJob" % ("*"*20))
  584.                         
  585.                         job_id = self.job_id
  586.                         
  587.                         soap = utils.cat(
  588. """<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string" SOAP-ENV:mustUnderstand="1">$job_id</jobId></SOAP-ENV:Header><SOAP-ENV:Body><Fax:EndJob xmlns:Fax="urn:Fax"><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">$job_id</jobId></Fax:EndJob></SOAP-ENV:Body></SOAP-ENV:Envelope>""")
  589.                         
  590.                         data = self.format_http(soap)
  591.  
  592.                         log.log_data(data)
  593.                         
  594.                         if log.is_debug():
  595.                             file('endjob.log', 'w').write(data)
  596.                         
  597.                         self.dev.writeSoapFax(data)
  598.                         ret = cStringIO.StringIO()
  599.                         
  600.                         while self.dev.readSoapFax(8192, ret, timeout=5):
  601.                             pass
  602.                             
  603.                         ret = ret.getvalue()
  604.                         
  605.                         if log.is_debug():
  606.                             file('endjob_ret.log', 'w').write(ret)
  607.                         
  608.                         log.log_data(ret)
  609.                         self.dev.closeSoapFax()
  610.                         
  611.                         if self.get_error_code(ret) == HTTP_OK:
  612.                             fax_send_state = FAX_SEND_STATE_SUCCESS
  613.                         else:
  614.                             fax_send_state = FAX_SEND_STATE_ERROR
  615.                     
  616.                     elif fax_send_state == FAX_SEND_STATE_CANCELJOB: # -------------- CancelJob (110, 80, 0)
  617.                         log.debug("%s State: CancelJob" % ("*"*20))
  618.                         
  619.                         job_id = self.job_id
  620.                         
  621.                         soap = utils.cat(
  622. """<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string" SOAP-ENV:mustUnderstand="1">$job_id</jobId></SOAP-ENV:Header><SOAP-ENV:Body><Fax:CancelJob xmlns:Fax="urn:Fax"><jobId xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">$job_id</jobId></Fax:CancelJob></SOAP-ENV:Body></SOAP-ENV:Envelope>""")
  623.                         
  624.                         data = self.format_http(soap)
  625.                         
  626.                         log.log_data(data)
  627.                         
  628.                         if log.is_debug():
  629.                             file('canceljob.log', 'w').write(data)
  630.                         
  631.                         self.dev.writeSoapFax(data)
  632.                         ret = cStringIO.StringIO()
  633.                         
  634.                         while self.dev.readSoapFax(8192, ret, timeout=5):
  635.                             pass
  636.                             
  637.                         ret = ret.getvalue()
  638.                         
  639.                         if log.is_debug():
  640.                             file('canceljob_ret.log', 'w').write(ret)
  641.                         
  642.                         log.log_data(ret)
  643.                         self.dev.closeSoapFax()
  644.                         
  645.                         if self.get_error_code(ret) == HTTP_OK:
  646.                             fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
  647.                         else:
  648.                             fax_send_state = FAX_SEND_STATE_ERROR                        
  649.                         
  650.  
  651.                     elif fax_send_state == FAX_SEND_STATE_CLOSE_SESSION: # -------------- Close session (110, 170, 0)
  652.                         log.debug("%s State: Close session" % ("*"*20))
  653.                         log.debug("Closing session...")
  654.  
  655.                         try:
  656.                             mm.close()
  657.                         except NameError:
  658.                             pass
  659.  
  660.                         try:
  661.                             ff.close()
  662.                         except NameError:
  663.                             pass
  664.  
  665.                         time.sleep(1)
  666.  
  667.                         self.dev.closeSoapFax()
  668.                         self.dev.close()
  669.                         
  670.                         fax_send_state = FAX_SEND_STATE_DONE # Exit inner state machine
  671.  
  672.  
  673.             elif state == STATE_CLEANUP: # --------------------------------- Cleanup (120, 0, 0)
  674.                 log.debug("%s State: Cleanup" % ("*"*20))
  675.  
  676.                 if self.remove_temp_file:
  677.                     log.debug("Removing merged file: %s" % self.f)
  678.                     try:
  679.                         os.remove(self.f)
  680.                         log.debug("Removed")
  681.                     except OSError:
  682.                         log.debug("Not found")
  683.  
  684.                 state = STATE_DONE # Exit outer state machine
  685.  
  686.  
  687.     def get_error_code(self, ret):
  688.         if not ret: return HTTP_ERROR
  689.         
  690.         match = http_result_pat.match(ret)
  691.  
  692.         if match is None: return HTTP_OK
  693.         try:
  694.             code = int(match.group(1))
  695.         except (ValueError, TypeError):
  696.             code = HTTP_ERROR
  697.             
  698.         return code
  699.         
  700.         
  701.     def format_http(self, soap, content_type="text/xml; charset=utf-8"):
  702.         host = self.http_host
  703.         soap_len = len(soap)
  704.         
  705.         return utils.cat(
  706. """POST / HTTP/1.1\r
  707. Host: $host\r
  708. User-Agent: hplip/2.0\r
  709. Content-Type: $content_type\r
  710. Content-Length: $soap_len\r
  711. Connection: close\r
  712. SOAPAction: ""\r
  713. \r
  714. $soap""")
  715.  
  716.  
  717.  
  718.  
  719.